package part.e;

import java.util.LinkedList;
import java.util.Queue;

public class ThreadPool {

	private Queue<Runnable> taskQueue;
	private Thread[] threads;
	private static final int DEFAULT_POOL_SIZE = 2;
	private int size;

	public ThreadPool() {
		size = DEFAULT_POOL_SIZE;
		taskQueue = new LinkedList<Runnable>();
		threads = new IdleThread[size];
		for (int i = 0; i < size; i++) {
			threads[i] = new IdleThread(this);
			threads[i].start();
		}
	}

	public ThreadPool(int size) {
		this.size = size;
		taskQueue = new LinkedList<Runnable>();
		threads = new IdleThread[size];
		for (int i = 0; i < size; i++) {
			threads[i] = new IdleThread(this);
			threads[i].start();
		}
	}

	public synchronized void add(Runnable task) {
		taskQueue.add(task);
		notify();
	}

	public void stopPool() {
		for (Thread thread : threads) {
			thread.interrupt();
		}
	}

	public synchronized Runnable getTask() {
		while (taskQueue.isEmpty()) {
			try {
				wait();
			} catch (InterruptedException ie) {
				return null;
			}
		}
		return taskQueue.remove();
	}

	private class IdleThread extends Thread {

		private ThreadPool pool;

		public IdleThread(ThreadPool pool) {
			this.pool = pool;
		}

		public void run() {
			Runnable task = null;
			while (!isInterrupted()) {
				task = pool.getTask();
				if (task != null) {
					task.run();
					task = null;
				}
			}
		}
	}
}
